import sys
import os
import shutil
import unittest
import datetime
from copy import deepcopy

import multiprocessing as MulProcess

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))

from framework.config_parser import ConfigFileParser
from framework.options_combiner import OptionCombiner
from common.benchmark_var import StatusCode


class OptionCombinerTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        cls.option_merger = OptionCombiner()
        cls.output_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "output_dir"))

    @classmethod
    def tearDownClass(cls) -> None:
        if os.path.isdir(cls.output_dir):
            shutil.rmtree(cls.output_dir)

    def setUp(self) -> None:
        pass

    def tearDown(self) -> None:
        pass

    @classmethod
    def _create_default_options(self):
        default_options = {
            "general": {
                "action": "standard",
                "test_target": ["ServerSuite"],
                "iterations": 1,
                "copies": 1,
                "multithread": 1,
                "taskset": [],
                "report": ["all"],
                "output_dir": os.path.abspath(os.path.join(os.path.dirname(__file__), "output_dir")),
                "skip_fail": 0,
                "debug": 0,
                "manufacturer": "",
                "server_model": "",
                "cpu_model": "",
                "netcards": "",
                "raid": "",
                "display_cards": "",
                "hardware_others": "",
                "os": "",
                "software_others": "",
                "tester_name": "",
                "test_date": datetime.datetime.now().strftime('%Y.%m.%d')
            },
            "compiler": {
                "base_dir": "/usr/bin",
                "LD_LIBRARY_PATH": "",
                "CC": "/usr/bin/gcc",
                "CC_VERSION": "-v"
            }
        }
        return default_options

    def test_combine_options1(self):
        cmd_option = {"iterations": 2}
        conf_options = {
            "general": {
                "test_target": ["ServerSuite"],
                "report": ["txt", "pdf"]
            },
            "compiler": {
                "base_dir": "/usr/bin",
                "LD_LIBRARY_PATH": "",
                "CC": "/usr/bin/gcc",
                "CC_VERSION": "-v"
            }
        }
        options = self.option_merger.combine_options(conf_options, cmd_option)

        expected_options = self._create_default_options()
        expected_options["general"]["iterations"] = 2
        expected_options["general"]["report"] = ["txt", "pdf"]

        self.assertEqual(options, expected_options)

    def test_combine_options2(self):
        cmd_option = {"iterations": 3}
        conf_options = {
            "general": {
                "iterations": 2,
                "test_target": ["ServerSuite"],
            },
            "compiler": {
                "base_dir": "/usr/bin",
                "LD_LIBRARY_PATH": "",
                "CC": "/usr/bin/gcc",
                "CC_VERSION": "-v"
            }
        }
        options = self.option_merger.combine_options(conf_options, cmd_option)
        expected_options = self._create_default_options()
        expected_options["general"]["iterations"] = 3

        self.assertEqual(options, expected_options)

    def test_verify_options(self):
        options = self._create_default_options()
        options["general"]["iterations"] = 3
        options["general"]["report"] = ["all", "pdf"]
        cpu_num = MulProcess.cpu_count() + 2
        options["general"]["taskset"] = [cpu_num]

        try:
            self.option_merger.verify_options(options)
        except SystemExit as e:
            self.assertEqual(e.code, 1)


if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(OptionCombinerTestCase)
    unittest.TextTestRunner(verbosity=2).run(suite)